package logic;

import java.io.IOException;
import java.util.ArrayList;
import model.EnergyProfile;
import model.PredictionEnergyProfile;

import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;

public class DataInitializer {
	
	public static final int ANNUAL_ENERGY=10000;
	
	public static void main(String[] args) {
		
		DataInitializer di = new DataInitializer();
		try {
		ArrayList<EnergyProfile> reslist = di.processResidentialData(ANNUAL_ENERGY);
		ArrayList<EnergyProfile> comlist = di.processCommercialData(ANNUAL_ENERGY);
		ArrayList<EnergyProfile> indlist = di.processIndustrialData(ANNUAL_ENERGY);
		
		ArrayList<EnergyProfile> alllist = new ArrayList<EnergyProfile>();
		alllist.addAll(reslist);
		alllist.addAll(comlist);
		alllist.addAll(indlist);
		
		String destination = "src\\resources\\rg\\alldatawithmonths.csv";
		di.writeProcessedData(alllist,destination);
		
		String nomonthtraining = "src\\resources\\weka\\weka_nomonth_training.csv";
		ArrayList<PredictionEnergyProfile> predlist = di.processLogisticRegression(nomonthtraining);
		System.out.println(nomonthtraining);
		
		//String[] profilerargs = {"3profiles.csv"};
		//EnergyProfilerFile.main(profilerargs);
/*		String daydatadest = "src\\resources\\rg\\monthday";
		
		
		for (int month=0; month<12;month++) {
			di.writeProcessedMonthDayData(alllist, daydatadest+month+"Day"+".csv", month, EnergyProfile.DAY_TYPE_WEEKDAY);
			di.writeProcessedMonthDayData(alllist, daydatadest+month+"End"+".csv", month, EnergyProfile.DAY_TYPE_WEEKEND);
		}
		
		String weekdaydatadest = "src\\resources\\rg\\weekday";
		
		String weekenddatadest = "src\\resources\\rg\\weekend";

		for (int month=0; month<12;month++) {
			di.writeProcessedDayData(alllist, weekdaydatadest+".csv", EnergyProfile.DAY_TYPE_WEEKDAY);
			di.writeProcessedDayData(alllist, weekenddatadest+".csv", EnergyProfile.DAY_TYPE_WEEKEND);
		}
*/		
		}		
		catch (IOException e) {
			System.out.println(e);
		}
	}
	
	public DataInitializer() {
	}
	
	public ArrayList<EnergyProfile> initializeData() {
		return initializeData(ANNUAL_ENERGY);
	}
	
	public ArrayList<EnergyProfile> initializeData(int annualEnergy) {
		ArrayList<EnergyProfile> al = new ArrayList<EnergyProfile>();
		try {
			al.addAll(processResidentialData(annualEnergy));
			al.addAll(processCommercialData(annualEnergy));
			al.addAll(processIndustrialData(annualEnergy));
			}
			catch (IOException e) {
				System.out.println(e);
			}
		return al;
	}
/**
Create usage combinations			
base + water heater etc			
load type	base	heating	cooling
	baseload	baseboard	central air
		electric furnace	
		space heat	
		water heat	
Combos			
	BL	x	AC
	BL	x	x
	BL	BB	x
	BL	BB	AC
	BL	EF	x
	BL	EF	AC
	BL	SH	x
	BL	SH	AC
	BL	WH	x
	BL	WH	AC
 * @throws IOException 
 */

	private static final String rgDir = "src\\resources\\rg\\";
	public static final String rgResBaseLoadData = rgDir+"rgResBaseLoadData" +".csv";
	public static final String rgResCentralAirData = rgDir+"rgResCentralAirData"+".csv";
	public static final String rgResBaseBoardData = rgDir+"rgResBaseBoardData"+".csv";
	public static final String rgResElectricFurnaceData = rgDir+"rgResElectricFurnaceData"+".csv";
	public static final String rgResSpaceHeatData = rgDir+"rgResSpaceHeatData"+".csv";
	public static final String rgResWaterHeatData = rgDir+"rgResWaterHeatData"+".csv";
	//public static final String INDUSTRY_RESIDENTIAL = "Residential";
	public static final String[] USAGETYPE_RESIDENTIAL = {"BaseLoad","BaseLoad&CentralAir",
		"BaseLoad&BaseBoard","BaseLoad&ElectricFurnace","BaseLoad&SpaceHeat","BaseLoad&WaterHeat",
		"BaseLoad&CentralAir&BaseBoard","BaseLoad&CentralAir&ElectricFurnace",
		"BaseLoad&CentralAir&SpaceHeat","BaseLoad&CentralAir&WaterHeat"	};
	// create combos
	private ArrayList<EnergyProfile> processResidentialData( double annualEnergy) throws IOException {
		// create combination files and store them
		String industry = EnergyProfile.INDUSTRY[EnergyProfile.RESIDENTIAL];
		ArrayList<EnergyProfile> al = new ArrayList<EnergyProfile>();
		EnergyProfile rgResBaseLoadProfile = processIESOData(rgResBaseLoadData,"BaseLoad",industry, annualEnergy);
		
		//AC
		EnergyProfile rgResCentralAirProfile = processIESOData(rgResCentralAirData,"CentralAir",industry,annualEnergy);
		
		//heating
		EnergyProfile rgResBaseBoardProfile = processIESOData(rgResBaseBoardData,"BaseBoard",industry,annualEnergy);
		EnergyProfile rgResElectricFurnaceProfile = processIESOData(rgResElectricFurnaceData,"ElectricFurnance",industry,annualEnergy);
		EnergyProfile rgResSpaceHeatProfile = processIESOData(rgResSpaceHeatData,"SpaceHeat",industry,annualEnergy);
		EnergyProfile rgResWaterHeatProfile = processIESOData(rgResWaterHeatData,"WaterHeat",industry,annualEnergy);
		
		al.add(rgResBaseLoadProfile);
		EnergyProfile BLACProfile = EnergyProfile.addEnergyProfiles(rgResBaseLoadProfile, rgResCentralAirProfile);
		EnergyProfile BLBBProfile = EnergyProfile.addEnergyProfiles(rgResBaseLoadProfile, rgResBaseBoardProfile);
		EnergyProfile BLEFProfile = EnergyProfile.addEnergyProfiles(rgResBaseLoadProfile, rgResElectricFurnaceProfile);
		EnergyProfile BLSHProfile = EnergyProfile.addEnergyProfiles(rgResBaseLoadProfile, rgResSpaceHeatProfile);
		EnergyProfile BLWHProfile = EnergyProfile.addEnergyProfiles(rgResBaseLoadProfile, rgResWaterHeatProfile);
		
		al.add(BLACProfile);
		al.add(BLBBProfile);
		al.add(BLEFProfile);
		al.add(BLSHProfile);
		al.add(BLWHProfile);
		
		EnergyProfile BLACBBProfile = EnergyProfile.addEnergyProfiles(BLACProfile, rgResBaseBoardProfile);
		EnergyProfile BLACEFProfile = EnergyProfile.addEnergyProfiles(BLACProfile, rgResElectricFurnaceProfile);
		EnergyProfile BLACSHProfile = EnergyProfile.addEnergyProfiles(BLACProfile, rgResSpaceHeatProfile);
		EnergyProfile BLACWHProfile = EnergyProfile.addEnergyProfiles(BLACProfile, rgResWaterHeatProfile);
		
		al.add(BLACBBProfile);
		al.add(BLACEFProfile);
		al.add(BLACSHProfile);
		al.add(BLACWHProfile);
		
		return al;
	}
	
	private ArrayList<EnergyProfile> processTypeData(String[] strtypes, String industry, String filestart, double annualEnergy)throws IOException {
		// create profile objects
		ArrayList<EnergyProfile> al = new ArrayList<EnergyProfile>();
		for (int i=0; i<strtypes.length; i++) {
			String filename = filestart+strtypes[i]+"Data.csv";
			EnergyProfile energyProfile = processIESOData(filename,strtypes[i],industry, annualEnergy);
			al.add(energyProfile);
		}
		return al;		
	}
	
	public static final String cgDir = "src\\resources\\cg\\";
	public static final String cgCommChurchData = cgDir+"cgCommChurchData"+".csv";
	//public static final String INDUSTRY_COMMERCIAL = "Commercial";
	public static final String[] USAGETYPE_COMMERCIAL = {"Church","Education","Food","Health","Hotels",
		"MultiRes","Offices","OtherRetail","Rec","Services","Warehouse"};
	public static final int[] ELECTRICITY_INTENSITY_COMMERCIAL = {110,68,490,225,490,490,343,229,177,96,148};
	private ArrayList<EnergyProfile> processCommercialData(double annualEnergy)throws IOException {
		//create cgDir, work the datafile array, make arraylist return
		// create profile objects
		String[] strtypes = USAGETYPE_COMMERCIAL;
		String filestart = cgDir+"cgComm";
		String industry = EnergyProfile.INDUSTRY[EnergyProfile.COMMERCIAL];
		return processTypeData(strtypes,industry,filestart,annualEnergy);		
	}
	
	public static final String siDir = "src\\resources\\si\\";
	public static final String SindChemicalData = siDir+"SindChemicalData"+".csv";
	//public static final String INDUSTRY_INDUSTRIAL = "Industrial";
	public static final String[] USAGETYPE_INDUSTRIAL  = {"Chemical","Clothing","Construction","Electrical",
		"FabricatedMetals","Farm","Food","Machinery","Mine","NonMetallic",
		"OtherMfg","PrimaryMetals","Transport","Wood"};
	private ArrayList<EnergyProfile> processIndustrialData(double annualEnergy)throws IOException {
		// create cgDir, work the datafile array, make arraylist return
		// create profile objects
		String[] strtypes = USAGETYPE_INDUSTRIAL;
		String filestart = siDir+"Sind";
		String industry = EnergyProfile.INDUSTRY[EnergyProfile.INDUSTRIAL];
		return processTypeData(strtypes,industry,filestart,annualEnergy);	
	}
	/**
	 * Multiply out days with %month %day and annual usage.
	 * 
	 * @param source
	 * @param Destination
	 * @param annualEnergy
	 * @throws IOException 
	 */
	private EnergyProfile processIESOData(String source, String usageType, String industry, double annualEnergy ) throws IOException {
		EnergyProfile energyProfile = new EnergyProfile();
		CsvReader reader = new CsvReader(source);
		reader.readHeaders();
		
		//Food usage type is used twice. separate industrial and commercial
		if (usageType.equals("Food")) {
			if (EnergyProfile.INDUSTRY[EnergyProfile.COMMERCIAL].equals(industry))
				energyProfile.setUsageType(usageType+EnergyProfile.INDUSTRY[EnergyProfile.COMMERCIAL]);
			else //if (industry.equals(DataInitializer.INDUSTRY_INDUSTRIAL))
				energyProfile.setUsageType(usageType+EnergyProfile.INDUSTRY[EnergyProfile.INDUSTRIAL]);
		} else {
			energyProfile.setUsageType(usageType);
		}
		energyProfile.setIndustry(industry);
		//String useHeader = reader.getHeader(0);
		
		while (reader.readRecord())
		{
			double percentMonth = Double.parseDouble(reader.get("% Month"));
			double percentDay = Double.parseDouble(reader.get("% Day"));
			double doubleArray[]= new double[24];

			int month = Integer.parseInt(reader.get("Month")) -1; //set the index to -1
			
			for (int i=0; i<24; i++) {
				doubleArray[i] = annualEnergy * percentMonth * percentDay *
				Double.parseDouble(reader.get(String.valueOf(i+1)));
			}
			if (EnergyProfile.DAY_TYPE[EnergyProfile.WEEKDAY].equals(reader.get("Daytype").trim())) {
				energyProfile.getMonthWeekDayProfile()[month]=doubleArray;
			}else{
				energyProfile.getMonthWeekEndProfile()[month]=doubleArray;
			}
		}
		
		reader.close();
		return energyProfile;
	}
	
	
	/**
	 * save processed data
	 * 
	 * @param energyProfile
	 * @param destination
	 */
	private void writeProcessedData(ArrayList<EnergyProfile> alllist, String destination){
		CsvWriter writer = new CsvWriter(destination);
		try {
			writer.writeRecord(EnergyProfile.WRITE_HEADER, false);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		ArrayList<String[]> records = new ArrayList<String[]>();
		
		for (EnergyProfile energyprofile: alllist) {
			energyprofile.normalizeData();
			for (String[] rec : energyprofile.getRecords())
				records.add(rec);
		}
		 for (String[] singlerecord : records)
			try {
				writer.writeRecord(singlerecord, false);
			} catch (IOException e) {
				e.printStackTrace();
			}
		writer.close();
	}
	
	
	public ArrayList<PredictionEnergyProfile> processLogisticRegression(String source) throws IOException {
		ArrayList<PredictionEnergyProfile> list = new ArrayList<PredictionEnergyProfile>();
		
		CsvReader reader = new CsvReader(source);
		reader.readHeaders();
		String[] headers = reader.getHeaders();
		
		while (reader.readRecord())
		{
			PredictionEnergyProfile profile = new PredictionEnergyProfile();
			profile.setUsageType(reader.get(headers[0]));
			profile.setIntercept(Double.parseDouble(reader.get(headers[headers.length-1])));
			profile.setDaytype(Double.parseDouble(reader.get("Daytype")));
			
			boolean hasIndustry = false;
			boolean hastMonth = false;
			for (String headeritem: headers) {
				if (("Industry="+EnergyProfile.INDUSTRY[0]).equals(headeritem))
					hasIndustry = true;
				if (("Month="+EnergyProfile.MONTH[0]).equals(headeritem))
					hastMonth = true;
			}
			
			if (hasIndustry) {
				for(int i=0;i<EnergyProfile.INDUSTRY.length;i++) {
					profile.getIndustry()[i] = Double.parseDouble(reader.get("Industry="+EnergyProfile.INDUSTRY[i])); 
				}
			}else // then this has NO Industry
				profile.setIndustry(null);

			if (hastMonth) {
				for (int i=0; i<EnergyProfile.MONTH.length; i++) {
					profile.getMonth()[i] = Double.parseDouble(reader.get("Month="+EnergyProfile.MONTH[i]));
				}
			}else // then this has NO months
				profile.setMonth(null);
			
			for (int i=0; i<24; i++) {
				profile.getHour()[i] = Double.parseDouble(reader.get(String.valueOf(i+1)));
			}
			
			list.add(profile);
		}
		reader.close();
		return list;
	}
	
	/*
	private void writeProcessedMonthDayData(ArrayList<EnergyProfile> alllist, String destination, int month, String daytype){
		CsvWriter writer = new CsvWriter(destination);
		try {
			writer.writeRecord(EnergyProfile.WRITE_HEADER, false);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		ArrayList<String[]> records = new ArrayList<String[]>();
		
		for (EnergyProfile energyprofile: alllist) {
			energyprofile.normalizeData();
			String[] rec = energyprofile.getMonthDayRecord(month,daytype);
			records.add(rec);
		}
		 for (String[] singlerecord : records)
			try {
				writer.writeRecord(singlerecord, false);
			} catch (IOException e) {
				e.printStackTrace();
			}
		writer.close();
	}
	
	
	private void writeProcessedDayData(ArrayList<EnergyProfile> alllist, String destination, String daytype){
		CsvWriter writer = new CsvWriter(destination);
		try {
			writer.writeRecord(EnergyProfile.WRITE_HEADER, false);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		ArrayList<String[]> records = new ArrayList<String[]>();
		
		for (EnergyProfile energyprofile: alllist) {
			energyprofile.normalizeData();
			//String[] rec = energyprofile.getDayRecord(daytype);
			
			for (int month=0;month<12;month++) {
				String[] rec = energyprofile.getMonthDayRecord(month,daytype);
				records.add(rec);
			}
		}
		 for (String[] singlerecord : records)
			try {
				writer.writeRecord(singlerecord, false);
			} catch (IOException e) {
				e.printStackTrace();
			}
		writer.close();
	}
*/
	
}
